from typing import Any, Dict, List, Text

from rasa_sdk import Action, Tracker
from rasa_sdk.events import SlotSet
from rasa_sdk.executor import CollectingDispatcher

from datetime import datetime

from scipy.stats import logistic
from sqlalchemy import and_

from .db import SessionLocal
from .db_table_class import (
    LogisticsCompany,
    OrderInfo,
    Logistics,
    LogisticsComplaint,
    LogisticsComplaintsRecord,
)
from sqlalchemy.orm import joinedload

class GetLogisticsCompanys(Action):
    """查询支持的快递公司"""

    def name(self) -> str:
        return "action_get_logistics_companys"

    def run(
        self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[str, Any]
    ) -> List[Dict[Text, Any]]:
        # 从db文件中引入SessionLocal用于引入session工程
        with SessionLocal() as session:
            logistics_companys = session.query(LogisticsCompany).all()
        # 规范字符输出格式
        logistics_companys = "".join(
            [f"- {i.company_name}\n" for i in logistics_companys]
        )
        # 若没有数据则返回无
        if logistics_companys == "":
            logistics_companys = "- 无"
        # 用状态追踪器给出回答，给出回答的格式
        dispatcher.utter_message(f"支持的快递有:\n{logistics_companys}")
        # 当有需要修改的槽时才需要设置返回值
        return []


class GetLogisticsInfo(Action):
  """查询物流信息"""

  def name(self) -> str:
    return "action_get_logistics_info"

  def run(
    self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[str, Any]
  ) -> List[Dict[Text, Any]]:
    # 从槽中获取订单ID
    order_id = tracker.get_slot("order_id")
    # 1查询订单
    with SessionLocal() as session:
      order_info = (
        session.query(OrderInfo)
        .options(joinedload(OrderInfo.logistics))
        .options(joinedload(OrderInfo.order_detail))
        .filter_by(order_id=order_id)
        .first()
      )
    # 2获取订单物流信息
    logistics = order_info.logistics[0]
    message = [f"- **订单ID**：{order_id}"]
    message.extend(
      [
        f" - {order_detail.sku_name} × {order_detail.sku_count}"
        for order_detail in order_info.order_detail
      ]
    )
    message.append(f"- **物流ID**：{logistics.logistics_id}")
    message.append("- **物流信息**：")
    message.append(" - " + "\n - ".join(logistics.logistics_tracking.split("\n")))
    dispatcher.utter_message("\n".join(message))
    return [SlotSet("logistics_id", logistics.logistics_id)]



# 制作物流投诉部分，用户选择投诉的订单后，提取投诉内容，提交投诉信息，
# 从数据库中拿出投诉的清单供用户选择，设置槽的值
class AskLogisticsComplaint(Action):
  """查询物流信息"""

  def name(self) -> str:
    return "action_ask_logistics_complaint"

  def run(
    self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[str, Any]
  ) -> List[Dict[Text, Any]]:
      # 1获取订单ID和物流 ID
      user_id=tracker.get_slot("user_id")
      order_id = tracker.get_slot("order_id")
      logistics_id = tracker.get_slot("logistics_id")
      # 2从数据库中取出用户想投诉的物流订单
      with SessionLocal() as session:
        logistic_status= (
          session.query(Logistics).filter_by(logistics_id=logistics_id).first()
        )
      status="已签收" if logistic_status.delivered_time is not None else "已发货"
      # 3将得到物流清单进行分类输出，并加上"其他"和"取消投诉"
      with SessionLocal() as session:
          logistics_complaint_names = (
              session.query(LogisticsComplaint).filter_by(logistics_status=status).all()
          )
      # 4 用户选择物流投诉清单，或者选择其他时，槽的设置
      buttons = [
          {
              "title": logistics_complaint_name.logistics_complaint,
              "payload": f"/SetSlots(logistics_complaint={logistics_complaint_name.logistics_complaint})",
          }
          for logistics_complaint_name in logistics_complaint_names
      ]
      buttons.append(
          {
              "title": "其他",
              "payload": f"/SetSlots(logistics_complaint=other)",
          }
      )
      buttons.append(
          {
              "title": "取消投诉",
              "payload": f"/SetSlots(logistics_complaint=取消投诉)",
          }
      )
      dispatcher.utter_message(
          text="请选择投诉内容",
          buttons=buttons,
      )
      return []

class ActionRecordLogisticsComplaint(Action):
  """
  记录用户投诉的内容到数据库中
  """
  def name(self) -> str:
    return "action_record_logistics_complaint"

  def run(
    self, dispatcher: CollectingDispatcher, tracker: Tracker, domain: Dict[str, Any]
  ) -> List[Dict[Text, Any]]:
      # 1获取用户投诉的物流订单ID
      logistics_id = tracker.get_slot("logistics_id")
      order_id = tracker.get_slot("order_id")
      # 2获取用户投诉的内容

      logistics_complaint = tracker.get_slot("logistics_complaint")
      # 2.1当用户的投诉内容为其他时，从用户最近的对话中获取到投诉的内容
      if logistics_complaint == "other":
          logistics_complaint = tracker.latest_message["text"]
          SlotSet("logistics_complaint", logistics_complaint)
      # 2.2给用户提供反馈
      dispatcher.utter_message(text=f"客服已记录您对订单{order_id}的投诉，投诉内容为：{logistics_complaint}，将立即派工作人员处理")
      # 3将投诉内容记录到数据库中
      with SessionLocal() as session:
        session.add(LogisticsComplaintsRecord(
          logistics_id=logistics_id,
          logistics_complaint=logistics_complaint,
          user_id=tracker.get_slot("user_id"),
          complaint_time=datetime.now(),

        ))
        session.commit()
      return [SlotSet("logistics_complaint", logistics_complaint)]